use redis::aio::MultiplexedConnection;
use sea_orm::{DatabaseConnection, EntityTrait, Set};
use async_graphql::Result as GraphQLResult;
use snowid::SnowID;
use sqlx::types::chrono::Utc;
use crate::entity::product_advertising;
use crate::graphql::product_ad_graphql::{CreateProductADInput, ProductADObject};

// product_ad_graphql 实现
pub async fn get_advertising_list(
    db: &DatabaseConnection,
    conn: &MultiplexedConnection,
) -> GraphQLResult<Vec<ProductADObject>> {
    // 尝试从缓存获取
    let cached_result: Option<String> =
        redis::cmd("GET")
            .arg("product_ad_list")
            .query_async(&mut conn.clone())
            .await?;

    if let Some(cached_data) = cached_result {
        // 如果缓存中有数据，直接返回
        return Ok(serde_json::from_str::<Vec<ProductADObject>>(&cached_data)?);
    }

    let product_ad_models = product_advertising::Entity::find()
        .all(db)
        .await?;


    let product_ad_objects: Vec<ProductADObject> =
        product_ad_models
            .into_iter()
            .map(ProductADObject::from)
            .collect();

    // 将数据序列化为 JSON 字符串后存入 Redis
    let json_data = serde_json::to_string(&product_ad_objects)?;

    // 异步设置缓存，设置过期时间（例如：300秒）
    redis::cmd("SETEX")
        .arg("product_ad_list")
        .arg(300) // 5分钟过期
        .arg(&json_data)
        .query_async::<()>(&mut conn.clone())
        .await?;

    Ok(product_ad_objects)
}

pub async fn create_advertising(
    db: &DatabaseConnection,
    conn: &MultiplexedConnection,
    input: CreateProductADInput,
) -> GraphQLResult<ProductADObject> {
    let now = Utc::now().naive_utc();

    let id = SnowID::new(1)?.generate();

    let new_ad = product_advertising::ActiveModel {
        id: Set(id), // 使用生成的雪花ID
        product_id: Set(input.product_id.parse()?),
        cover_addr: Set(input.cover_addr.clone()),
        create_time: Set(now),
        update_time: Set(now),
    };

    let ad = product_advertising::Entity::insert(new_ad)
        .exec_with_returning(db)
        .await?;

    redis::cmd("DEL")
        .arg("product_ad_list")
        .query_async::<()>(&mut conn.clone())
        .await?;

    Ok(ProductADObject::from(ad))
}

pub async fn delete_advertising(
    db: &DatabaseConnection,
    conn: &MultiplexedConnection,
    id: String,
) -> GraphQLResult<bool> {


    let result = product_advertising::Entity::delete_by_id(id.parse::<u64>()?)
        .exec(db)
        .await?;


    redis::cmd("DEL")
        .arg("product_ad_list")
        .query_async::<()>(&mut conn.clone())
        .await?;

    Ok(result.rows_affected > 0)
}